# -*- coding: utf-8 -*-
"""
@author: Tim Lux
@license: AGPL
"""

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import time

# settings for gecko and firefox
options = Options()
options.headless = True

#global variables of state of driver
driver_open = False
open_stocks = []
bad_stocks = []

def getStockQuotes(dict_stocks):
    """operates firefox and stock-tabs, returns quotes
    
    Keyword arguments:
        dict_stocks -- dict_stockstionary {"SYML": {"amout":1, "value": 0}}
    
    return:
        dict_stocks {"SYML": {"amount":2, "value": 100, "total_value":200}, "_all": 200}
            last key "_all" -->  total value of all stocks        
    """
    global open_stocks
    global driver
        
    #open gecko with blank if no gecko open
    _getGecko()
    
    if(dict_stocks != {}):
        #if no stock is open, open all in list
        if len(open_stocks) <= 0:
            _openAll(dict_stocks)
        
        #compare open tabs to requested dict... close/open
        _compareToOpenTabs(dict_stocks)
        
        #add _all to dict for add total values
        dict_stocks["_all"] = 0
        dict_stocks = _getStockQuotesFromDict(dict_stocks)    
    else:
        if(len(open_stocks) > 0):
            open_stocks_temp = open_stocks[:]
            for i in open_stocks_temp:
                _closeTab(i)
        dict_stocks["_all"] = 0
    
    return dict_stocks

def quitGecko():
    """close firefox+gecko and all tabs"""
    global driver_open
    if(driver_open == True):
        driver.delete_all_cookies()
        driver.quit()
        driver_open = False

def reset_browser():
    global open_stocks
    global driver
    print("reset browser")
    open_stocks = []
    driver.quit()
    _getGecko()
    
##############################################################################
#HELPER FUNCTIONS
##############################################################################
#Gecko Helper
def _getGecko():
    """deletes cookies, quits gecko"""
    #open firefox, assign driver
    global driver_open
    global driver
    if(driver_open == False):
        driver = webdriver.Firefox(options=options)
        driver_open = True
        _openBlank()

def _openBlank():
    """opens first stock-tab, closes cookie messages"""
    if(driver_open == True):
        annehmenXPath = '//*[@id="consent-page"]/div/div/div/div[2]/div[2]/form/button'
        driver.get("https://finance.yahoo.com/")
        
        #cookies accepted, they will be deleted in quitGecko, when session finished
        cookies = _findObj(annehmenXPath)
        cookies.click()
    else:
        print("openBlank failed due to closed Gecko")

##############################################################################
#tab management
def _openAll(dict_stocks):
    """opens new firefox with stock-tabs"""
    list_stocks = list(dict_stocks.keys())
    for i in list_stocks:
        if(i != '_all'):
            _setupNew(i, dict_stocks)

def _compareToOpenTabs(dict_stocks):
    """compares requested stocks to open tabs"""
    #if new stocks were added, open them in new tabs
    # --> iterate through list of demandes stock prices
    for i in dict_stocks:
        if i != '_all' and i not in open_stocks and i not in bad_stocks:
                _setupNew(i, dict_stocks)
    #if less tabs are needed close some
    # -->iterate through list open tabs
    for i in open_stocks:
        if i not in dict_stocks:
            _closeTab(i)
    
def _setupNew(symbol, dict_stocks):
    """opens new stock tabs"""
    global open_stocks
    if(symbol != '_all'):
        driver.execute_script("window.open()")
        driver.switch_to.window(driver.window_handles[len(open_stocks)+1])
        driver.get("https://finance.yahoo.com/quote/"+ symbol + "?p=" + symbol)
        open_stocks.append(symbol)
        try:
            quote = float(driver.find_element_by_xpath("//*[@id='quote-header-info']/div[3]/div[1]/div/span[1]").text)
        except:
            print("Stock not available")
            dict_stocks[symbol]["value"] = 0
            dict_stocks[symbol]["amount"] = 0
            dict_stocks[symbol]["total_value"] = 0
            bad_stocks.append(symbol)
            _closeTab(symbol)

def _closeTab(symbol):
    """closes tab of stock"""
    position = open_stocks.index(symbol) + 1
    driver.switch_to.window(driver.window_handles[position])
    driver.close()
    open_stocks.remove(symbol)
    driver.switch_to.window(driver.window_handles[0])

##############################################################################
#functions to get stock quotes
def _getStockQuotesFromDict(dict_stocks):
    """iterates all open tabs, assign stock values to dict_stockst
    
    Keyword arguments:
        dict_stocks -- dict_stockstionary {"SYML": {"amout":1, "value": 0}}
    
    return:
        dict_stocks with all stock values & total value
        {"SYML": {"amout":2, "value": 100, "total_value": 200}, "_all": 200}
    """
    global bad_stocks
    sum = 0
    for i in dict_stocks:
        if i != "_all" and i not in bad_stocks:
            tab_index = open_stocks.index(i) + 1
            driver.switch_to.window(driver.window_handles[tab_index])
            quote = float(driver.find_element_by_xpath("//*[@id='quote-header-info']/div[3]/div[1]/div/span[1]").text)
            dict_stocks[i]["value"] = quote
            dict_stocks[i]["total_value"] = round((quote*float(dict_stocks[i]["amount"])),2)
            sum += float(dict_stocks[i]["value"]) * float(dict_stocks[i]["amount"])
    dict_stocks["_all"] = round(sum,2)
    return dict_stocks

##############################################################################
#functions to find web elements better
def _findObj(obj):
    """scrolls down until element is found"""
    i=0
    scroll = 20
    while i<20:
        try:
            element = driver.find_element_by_xpath(obj)
        except:
            print("scoll down to find element")
        driver.execute_script("window.scrollTo(0, "+ str(scroll) + ")")
        i += 1
        scroll += scroll
    return element

#not used
def _waitObj(o):
    """waits for element when page loads in browser slowly"""
    i=0
    while i<20:
        try:
            elem = driver.find_element_by_xpath(o)
        except:
            print("scoll down to find element")
        i += 1
        time.sleep(0.3)
        print("sleep")
    return elem
